<?php

namespace App\Http\Controllers\Admin\Category;

use App\Services\CategoryService;
use App\Http\Controllers\Controller;
use App\Models\Category\Category;
use App\Models\Category\CategoryGroup;
use App\Transformers\Category\CategoryTransformer;
use Dingo\Api\Http\Response;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpKernel\Exception\HttpException;

class BaseController extends Controller
{
    /**
     * 在构造函数中的到注入的categoryService的模型
     */
    public $categoryService;

    /**
     * 分类的组名
     */
    public $type;

    public function __construct()
    {
        /**
         * 模型注入
         * $this->type 分类名称
         */

        $this->categoryService = new CategoryService(request(), $this->type);
    }

    /**
     * 查询所有分类
     */
    public function index(Request $request)
    {

        $data = $this->categoryService->list();

        /**
         * compact() 函数创建一个包含变量名和它们的值的数组。
         * var1	必需。可以是带有变量名的字符串，或者是一个变量数组。
         * var2,...	可选。可以是带有变量名的字符串，或者是一个变量数组。允许多个参数。
         * 返回值：	返回带有所有变量名和它们的值的数组。
         */
        return $this->response->array($data);
    }

    /**
     *  创建分类
     *
     * @param Request $request
     * @return Response|void
     * @throws ValidationException
     */
    public function store(Request $request)
    {
        $this->validateData($request);
        $pid = $request->input('pid');

        if (empty($pid)) {
            $request->offsetSet('top_id', 0);
            $request->offsetSet('pid', 0);
            $request->offsetSet('path', null);
        } else {
            $parent = Category::query()->findOrFail($pid);

            //获取分类组表中规定的最大分类级别
            $depth = CategoryGroup::query()
                ->where('id',$this->categoryService->category_group_id)
                ->first()
                ->depth;

            //判断是否超出了规定的最大级别
            if ($parent->level >= $depth){
                return $this->response->error('已超出规定的最大分类级别',422);
            }

            $request->offsetSet('top_id', $parent->top_id == 0 ? $parent->id : $parent->top_id);
            $request->offsetSet('pid', $parent->id);
            $request->offsetSet('path', $parent->top_id == 0 ? $parent->id : $parent->path . ',' . $parent->id);
            $request->offsetSet('level', $parent->level + 1);
        }

        $request->offsetSet('admin_id', $this->admin_user('id'));

        $name = $request->input('name');
        $nickname = $request->input('nickname');

        //preg_match函数可以根据正则表达式对字符串进行搜索匹配
        //[\x7f-\xff] 匹配所有汉字的
        if (empty($name) && preg_match("/^[\x{4e00}-\x{9fa5}]+$/u",$nickname)) {

            //implode() 函数返回由数组元素组合成的字符串。
            //pinyin用的是组件，可以将汉字转换为拼音
            $pinyin = implode('-', pinyin($nickname, true));
            $request->offsetSet('name', $pinyin);

        }else{

            if (empty($name)){
                return $this->response->error('添加失败 违反命名规则',422);
            }

        }

        $category = $this->categoryService->createCategory();

        if (empty($pid)){
            //在添加顶级分类时，将该顶级分类的top_id，设置为自己的id
            $category->where('id',$category->id)->update(['top_id'=>$category->id]);
        }

        if (!$category) {
            return $this->response->error('添加失败',422);
        }

        $this->categoryService->cacheCategory($category->id, $category);

        return $this->response->created();
    }


    /**
     * 更新
     *
     * @param $id
     * @param Request $request
     * @return Response|void
     * @throws ValidationException
     */
    public function update($id, Request $request)
    {
        $this->validateData($request);

        $category = $this->categoryService->getCacheCategory($id);

        if (empty($category)) {
            return $this->response->errorNotFound();
        }

        $pid = $request->input('pid');

        if (empty($pid)) {
            $request->offsetSet('top_id', 0);
            $request->offsetSet('pid', 0);
            $request->offsetSet('path', null);
        } else {
            $parent = Category::query()->findOrFail($pid);

            //获取分类组表中规定的最大分类级别
            $depth = CategoryGroup::query()
                ->where('id',$this->categoryService->category_group_id)
                ->first()
                ->depth;

            //判断是否超出了规定的最大级别
            if ($parent->level >= $depth){
                return $this->response->error('已超出规定的最大分类级别',422);
            }

            $request->offsetSet('top_id', $parent->top_id == 0 ? $parent->id : $parent->top_id);
            $request->offsetSet('pid', $parent->id);
            $request->offsetSet('path', $parent->top_id == 0 ? $parent->id : $parent->path . ',' . $parent->id);
            $request->offsetSet('level', $parent->level + 1);
        }

        $name = $request->input('name');

        if (empty($name) && preg_match("/[\x7f-\xff]/", $request->input('nickname'))) {
            $pinyin = implode('-', pinyin($request->input('nickname'), true));
            $request->offsetSet('name', $pinyin);
        } else {
            $request->offsetSet('name', $request->input('nickname'));
        }

        // 更新
        $category = $this->categoryService->updateCategory($category->id);

        if ($category) {
            $this->categoryService->cacheCategory($category->id, $category);
        }

        return $this->response->noContent();
    }


    /**
     * 获取详情
     *
     * @param $id
     * @param Request $request
     * @return \Dingo\Api\Http\Response|void
     */
    public function show($id, Request $request)
    {

        $category = Category::query()->where('category_group_id',$this->categoryService->category_group_id)->findOrFail($id);

        return $this->response->item($category, new CategoryTransformer());
    }


    /**
     * 删除
     *
     * @param $id
     * @return \Dingo\Api\Http\Response|void
     * @throws \Exception
     */
    public function destroy($id)
    {
        $data = Category::query()->with('children')->findOrFail($id);
        //获取当前类组的id
        $now_group_id = $this->categoryService->category_group_id;

        //判断要删除的分类的类组id是否为当前的类组的id
        if ($data->category_group_id != $now_group_id){
            return $this->response->errorBadRequest('请删除正确的分类id');
        }

        if (!$data->children->isEmpty()) {
            return $this->response->errorBadRequest('请删除下级后再删除');
        }

        $data->delete();

        return $this->response->noContent();
    }

    /**
     * 参数验证规则
     *
     * @param Request $request
     * @return array
     */
    public function rules(Request $request): array
    {
        $categoryService = new CategoryService(request(), $this->type);

        switch ($request->method()) {
            case 'GET':
                return [];
                break;
            case 'POST':
                return [
                    //bail在首次验证失败后立即终止验证。
                    'name' => ['bail', 'nullable', 'string', 'max:32', function ($attr, $value, $fail) use ($categoryService) {
                        $result = $categoryService->checkCategoryName(request()->input('pid', null), $value);
                        if (!$result) {
                            return $fail('分类名name重复');
                        }
                    }],
                    'nickname' => ['bail', 'required', 'string', 'max:50', function ($attr, $value, $fail) use ($categoryService) {
                        //属性的名称、属性的值以及$fail验证失败时应调用的回调
                        $result = $categoryService->checkCategoryNickname(request()->input('pid', null), $value);

                        if (!$result) {
                            return $fail('分类名nickname重复');
                        }
                    }],
                    'pid' => 'nullable|integer'
                ];
                break;
            case 'PATCH':
            case 'PUT':
                //从服务器中拿到id
                $id = route_parameter($this->type.'_category');

                if (empty($id)){
                    $id = route_parameter('id');
                }

                $category = $categoryService->getCacheCategory($id);

                if (empty($category)) {
                    throw new HttpException(404,'路由或ID错误');
                }

                return [
                    'name' => ['bail', 'nullable', 'string', 'max:32', function ($attr, $value, $fail) use ($categoryService,$id) {
                        $result = $categoryService->checkCategoryName(request()->input('pid', null), $value, $id);
                        if (!$result) {
                            return $fail('分类名name重复');
                        }
                    }],
                    'nickname' => ['bail', 'required', 'string', 'max:50', function ($attr, $value, $fail) use ($categoryService,$id) {
                        $result = $categoryService->checkCategoryNickname(request()->input('pid', null), $value, $id);
                        if (!$result) {
                            return $fail('分类名nickname重复');
                        }
                    }],
                    'pid' => 'nullable|integer'
                ];
                break;
        }
        return [];
    }
}
